package sleuthkit.gui;

import java.awt.CardLayout;
import java.awt.EventQueue;
import java.awt.GridLayout;
import java.io.File;
import java.io.FileInputStream;
import java.io.FileNotFoundException;
import java.io.IOException;
import java.util.ArrayList;
import java.util.InvalidPropertiesFormatException;
import java.util.Properties;

import javax.swing.DefaultListModel;
import javax.swing.ImageIcon;
import javax.swing.JButton;
import javax.swing.JComboBox;
import javax.swing.JFrame;
import javax.swing.JLabel;
import javax.swing.JList;
import javax.swing.JPanel;
import javax.swing.JScrollPane;
import javax.swing.JSplitPane;
import javax.swing.JTabbedPane;
import javax.swing.JTree;

import org.apache.log4j.Level;
import org.apache.log4j.Logger;

import sleuthkit.gui.actionlistener.AddEvidenceActionListener;
import sleuthkit.gui.actionlistener.AddMemoryImageActionListener;
import sleuthkit.gui.actionlistener.BtnCreateActionListener;
import sleuthkit.gui.actionlistener.GoToMainProcessingWindowActionListener;
import sleuthkit.gui.actionlistener.MyActionListener;
import sleuthkit.gui.actionlistener.RemoveEvidenceActionListener;
import sleuthkit.gui.filters.MyFileFilter;
import sleuthkit.util.StaticHelper;
import javax.swing.JTable;
import javax.swing.event.TreeExpansionListener;
import javax.swing.event.TreeExpansionEvent;

public class MainApplication {

	private static MainApplication instance;
	private JFrame frame;
	private Properties properties = new Properties();
	private Properties configuration = new Properties();
	private String mmls;
	private String fls;
	private String img_cat;
	private String ils;
	private String ifind;
	private String blkcalc;
	private String blkcat;
	private String blkls;
	private String blkstat;
	private String fcat;
	private String ffind;
	private String fsstat;
	private String hfind;
	private String icat;
	private String img_stat;
	private String istat;
	private String jcat;
	private String jls;
	private String mactime;
	private String mmcat;
	private String mmstat;
	private String tsk_comparedir;
	private String tsk_gettimes;
	private String tsk_loaddb;
	private String tsk_recover;
	private String fileSeperator = System.getProperty("file.separator");
	private String configFileName = "sleuthkit-gui.config";
	private ArrayList<String> casename = new ArrayList<String>();
	private ArrayList<String> investigatior = new ArrayList<String>();
	private String caseFolder;

	protected JButton btnCreate;
	private File currentCaseFolder;
	private Level logLevel;
	private String CurrentInvestigator;
	private JPanel cardPanel;
	private Logger log = Logger.getLogger(MainApplication.class);
	private JPanel addEvidence;
	private JTabbedPane mainProcessingWindow;
	private JList addEvidenceJList;
	private DefaultListModel addEvidenceDefaultListModel;
	private JPanel chooseCase;
	private JTree explorerViewJTree;
	private JTable table;
	private JScrollPane explorerViewJTreeJScrollPane;

	/**
	 * Launch the application.
	 */
	public static void main(String[] args) {
		StaticHelper.configLogger();
		EventQueue.invokeLater(new Runnable() {
			public void run() {
				try {
					MainApplication window = MainApplication.getInstance();
					window.frame.setVisible(true);
				} catch (Exception e) {
					e.printStackTrace();
				}
			}
		});
	}

	/**
	 * Create the application.
	 */
	public MainApplication() {
		setup();
		initialize();
	}

	private void setup() {
		// TODO Auto-generated method stub
		try {
			configuration.loadFromXML(new FileInputStream(properties
					.getProperty(configFileName,
							System.getProperty("user.home") + fileSeperator
									+ ".sleuthkit-gui" + fileSeperator
									+ configFileName)));
		} catch (InvalidPropertiesFormatException e) {
			// TODO Auto-generated catch block
			log.fatal("InvalidPropertiesFormatException", e);
			System.exit(1);
		} catch (FileNotFoundException e) {
			// TODO Auto-generated catch block
			log.fatal("FileNotFoundException", e);
			System.exit(2);
		} catch (IOException e) {
			// TODO Auto-generated catch block
			log.fatal("IOException", e);
			System.exit(3);
		}

		mmls = configuration.getProperty("mmls");
		fls = configuration.getProperty("fls");
		blkcalc = configuration.getProperty("blkcalc");
		blkcat = configuration.getProperty("blkcat");
		blkls = configuration.getProperty("blkls");
		blkstat = configuration.getProperty("blkstat");
		fcat = configuration.getProperty("fcat");
		ffind = configuration.getProperty("ffind");
		fls = configuration.getProperty("fls");
		fsstat = configuration.getProperty("fsstat");
		hfind = configuration.getProperty("hfind");
		icat = configuration.getProperty("icat");
		ifind = configuration.getProperty("ifind");
		ils = configuration.getProperty("ils");
		img_cat = configuration.getProperty("img_cat");
		img_stat = configuration.getProperty("img_stat");
		istat = configuration.getProperty("istat");
		jcat = configuration.getProperty("jcat");
		jls = configuration.getProperty("jls");
		mactime = configuration.getProperty("mactime");
		mmcat = configuration.getProperty("mmcat");
		mmls = configuration.getProperty("mmls");
		mmstat = configuration.getProperty("mmstat");
		tsk_comparedir = configuration.getProperty("tsk_comparedir");
		tsk_gettimes = configuration.getProperty("tsk_gettimes");
		tsk_loaddb = configuration.getProperty("tsk_loaddb");
		tsk_recover = configuration.getProperty("tsk_recover");
		caseFolder = configuration.getProperty("case folder");
		logLevel = Level.toLevel(configuration.getProperty("logLevel",
				(Logger.getRootLogger().getLevel()).toString()));

		setupHelper(configuration.getProperty("caseName"), ";", casename);
		setupHelper(configuration.getProperty("investigator"), ";",
				investigatior);
	}

	private void setupHelper(String casenames, String delimiter,
			ArrayList<String> result) {
		if (casenames != null) {
			String[] cases = casenames.split(delimiter);
			for (String string : cases) {
				result.add(string);
			}
		}
	}

	/**
	 * Initialize the contents of the frame.
	 */
	private void initialize() {
		frame = new JFrame();
		frame.setBounds(100, 100, 450, 300);
		frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
		frame.getContentPane().setLayout(new GridLayout(0, 1, 0, 0));

		cardPanel = new JPanel();
		frame.getContentPane().add(cardPanel);
		cardPanel.setLayout(new CardLayout(0, 0));

		chooseCase = new JPanel();
		cardPanel.add(chooseCase, "name_1353795309185814000");
		chooseCase.setLayout(null);

		JLabel lblCaseName = new JLabel("Case Name:");
		lblCaseName.setBounds(6, 12, 79, 16);
		chooseCase.add(lblCaseName);

		JComboBox comboBox = new JComboBox();

		comboBox.addActionListener(new MyActionListener(comboBox, this));
		comboBox.setBounds(97, 8, 347, 27);
		comboBox.setEditable(true);
		populateComboBox(comboBox, casename);
		chooseCase.add(comboBox);

		JLabel lblInvestigator = new JLabel("Investigator:");
		lblInvestigator.setBounds(6, 40, 79, 16);
		chooseCase.add(lblInvestigator);

		JComboBox comboBox_1 = new JComboBox();
		comboBox_1.setEditable(true);
		comboBox_1.setBounds(97, 36, 347, 27);
		populateComboBox(comboBox_1, investigatior);
		chooseCase.add(comboBox_1);

		btnCreate = new JButton("Open/Create...");
		btnCreate.setEnabled(false);
		btnCreate.addActionListener(new BtnCreateActionListener(comboBox,
				comboBox_1, this));
		btnCreate.setBounds(327, 243, 117, 29);
		chooseCase.add(btnCreate);

		addEvidence = new JPanel();
		cardPanel.add(addEvidence, "name_1353795309214809000");
		addEvidence.setLayout(null);

		JLabel lblNewLabel = new JLabel("Add images");
		lblNewLabel.setBounds(6, 13, 74, 16);
		addEvidence.add(lblNewLabel);

		JButton addEvidenceJButton = new JButton("+");
		addEvidenceJButton.setBounds(177, 8, 75, 29);
		addEvidenceJButton
				.addActionListener(new AddEvidenceActionListener(this));
		addEvidence.add(addEvidenceJButton);

		JButton goToMainProcessingWindow = new JButton("Next...");
		goToMainProcessingWindow
				.addActionListener(new GoToMainProcessingWindowActionListener(
						this, cardPanel));
		goToMainProcessingWindow.setBounds(369, 8, 75, 29);
		addEvidence.add(goToMainProcessingWindow);

		addEvidenceDefaultListModel = new DefaultListModel();

		JScrollPane scrollPane = new JScrollPane();
		scrollPane.setBounds(26, 41, 413, 210);
		addEvidence.add(scrollPane);
		addEvidenceJList = new JList(addEvidenceDefaultListModel);
		scrollPane.setViewportView(addEvidenceJList);

		JButton removeEvidence = new JButton("-");
		removeEvidence.addActionListener(new RemoveEvidenceActionListener(
				addEvidenceJList));
		removeEvidence.setBounds(245, 8, 75, 29);
		addEvidence.add(removeEvidence);

		JButton btnAddMemoryImage = new JButton("Mem +");
		btnAddMemoryImage.addActionListener(new AddMemoryImageActionListener(
				this));
		btnAddMemoryImage.setBounds(92, 8, 88, 29);
		addEvidence.add(btnAddMemoryImage);

		mainProcessingWindow = new JTabbedPane(JTabbedPane.TOP);
		cardPanel.add(mainProcessingWindow, "name_1353795799896232000");

		JSplitPane splitPane = new JSplitPane();
		mainProcessingWindow.addTab("ExplorerView", new ImageIcon(
				MainApplication.class.getResource("/images/iconOSX.jpg")),
				splitPane, null);

		explorerViewJTree = new JTree();
		explorerViewJTree.addTreeExpansionListener(new MyExplorerViewJTreeExpansionListener());
		explorerViewJTreeJScrollPane = new JScrollPane(
				explorerViewJTree,
				JScrollPane.VERTICAL_SCROLLBAR_AS_NEEDED,
				JScrollPane.HORIZONTAL_SCROLLBAR_AS_NEEDED);
		splitPane.setLeftComponent(explorerViewJTreeJScrollPane);

		JScrollPane ResultJScrollPane = new JScrollPane();
		splitPane.setRightComponent(ResultJScrollPane);

		table = new JTable();
		ResultJScrollPane.setViewportView(table);
	}

	public String getNameOfPane(JTabbedPane object) {
		if (mainProcessingWindow.equals(object)) {
			return "name_1353795799896232000";
		} else {
			return null;
		}
	}

	private void populateComboBox(JComboBox comboBox, ArrayList<String> values) {
		comboBox.addItem("");
		for (String value : values) {
			comboBox.addItem(value);
		}

	}

	public static MainApplication getInstance() {
		if (instance == null) {
			instance = new MainApplication();
		}

		return instance;
	}

	/**
	 * @return the frame
	 */
	public JFrame getFrame() {
		return frame;
	}

	/**
	 * @return the properties
	 */
	protected Properties getProperties() {
		return properties;
	}

	/**
	 * @return the configuration
	 */
	protected Properties getConfiguration() {
		return configuration;
	}

	/**
	 * @return the mmls
	 */
	public String getMmls() {
		return mmls;
	}

	/**
	 * @return the fls
	 */
	public String getFls() {
		return fls;
	}

	/**
	 * @return the img_cat
	 */
	public String getImg_cat() {
		return img_cat;
	}

	/**
	 * @return the ils
	 */
	public String getIls() {
		return ils;
	}

	/**
	 * @return the ifind
	 */
	public String getIfind() {
		return ifind;
	}

	/**
	 * @return the blkcalc
	 */
	public String getBlkcalc() {
		return blkcalc;
	}

	/**
	 * @return the blkcat
	 */
	public String getBlkcat() {
		return blkcat;
	}

	/**
	 * @return the blkls
	 */
	public String getBlkls() {
		return blkls;
	}

	/**
	 * @return the blkstat
	 */
	public String getBlkstat() {
		return blkstat;
	}

	/**
	 * @return the fcat
	 */
	public String getFcat() {
		return fcat;
	}

	/**
	 * @return the ffind
	 */
	public String getFfind() {
		return ffind;
	}

	/**
	 * @return the fsstat
	 */
	public String getFsstat() {
		return fsstat;
	}

	/**
	 * @return the hfind
	 */
	public String getHfind() {
		return hfind;
	}

	/**
	 * @return the icat
	 */
	public String getIcat() {
		return icat;
	}

	/**
	 * @return the img_stat
	 */
	public String getImg_stat() {
		return img_stat;
	}

	/**
	 * @return the istat
	 */
	public String getIstat() {
		return istat;
	}

	/**
	 * @return the jcat
	 */
	public String getJcat() {
		return jcat;
	}

	/**
	 * @return the jls
	 */
	public String getJls() {
		return jls;
	}

	/**
	 * @return the mactime
	 */
	public String getMactime() {
		return mactime;
	}

	/**
	 * @return the mmcat
	 */
	public String getMmcat() {
		return mmcat;
	}

	/**
	 * @return the mmstat
	 */
	public String getMmstat() {
		return mmstat;
	}

	/**
	 * @return the tsk_comparedir
	 */
	public String getTsk_comparedir() {
		return tsk_comparedir;
	}

	/**
	 * @return the tsk_gettimes
	 */
	public String getTsk_gettimes() {
		return tsk_gettimes;
	}

	/**
	 * @return the tsk_loaddb
	 */
	public String getTsk_loaddb() {
		return tsk_loaddb;
	}

	/**
	 * @return the tsk_recover
	 */
	public String getTsk_recover() {
		return tsk_recover;
	}

	/**
	 * @return the addEvidenceJList
	 */
	public JList getAddEvidenceJList() {
		return addEvidenceJList;
	}

	/**
	 * @return the addEvidenceDefaultListModel
	 */
	public DefaultListModel getAddEvidenceDefaultListModel() {
		return addEvidenceDefaultListModel;
	}

	/**
	 * @return the chooseCase
	 */
	public JPanel getChooseCase() {
		return chooseCase;
	}

	/**
	 * @return the explorerViewJTree
	 */
	public JTree getExplorerViewJTree() {
		return explorerViewJTree;
	}

	/**
	 * @return the fileSeperator
	 */
	protected String getFileSeperator() {
		return fileSeperator;
	}

	/**
	 * @return the configFileName
	 */
	protected String getConfigFileName() {
		return configFileName;
	}

	/**
	 * @return the casename
	 */
	protected ArrayList<String> getCasename() {
		return casename;
	}

	/**
	 * @return the investigatior
	 */
	protected ArrayList<String> getInvestigatior() {
		return investigatior;
	}

	/**
	 * @return the btnCreate
	 */
	public JButton getBtnCreate() {
		return btnCreate;
	}

	public String getCaseRoot() {
		return caseFolder;
	}

	/**
	 * @return the caseFolder
	 */
	protected String getCaseFolder() {
		return caseFolder;
	}

	/**
	 * @return the currentCaseFolder
	 */
	protected File getCurrentCaseFolder() {
		return currentCaseFolder;
	}

	/**
	 * @return the currentInvestigator
	 */
	protected String getCurrentInvestigator() {
		return CurrentInvestigator;
	}

	/**
	 * @return the cardPanel
	 */
	protected JPanel getCardPanel() {
		return cardPanel;
	}

	/**
	 * @return the log
	 */
	protected Logger getLog() {
		return log;
	}

	/**
	 * @return the addEvidence
	 */
	protected JPanel getAddEvidence() {
		return addEvidence;
	}

	/**
	 * @return the mainProcessingWindow
	 */
	public JTabbedPane getMainProcessingWindow() {
		return mainProcessingWindow;
	}

	public void setCurrentCaseFolder(File caseFolder) {

		this.currentCaseFolder = caseFolder;
		configuration.setProperty("Case.CurrentCaseFolder",
				caseFolder.getAbsolutePath());
		// configuration.setProperty("Case.CurrentInvestigator",
		// CurrentInvestigator);
	}

	public Level getLogLevel() {

		return logLevel;
	}
	
	

	/**
	 * @return the table
	 */
	protected JTable getTable() {
		return table;
	}

	/**
	 * @return the explorerViewJTreeJScrollPane
	 */
	public JScrollPane getExplorerViewJTreeJScrollPane() {
		return explorerViewJTreeJScrollPane;
	}

	public void showAddEvidence() {
		CardLayout cl = (CardLayout) cardPanel.getLayout();
		log.debug("show AddEvidence screen, name_1353795309214809000");
		cl.show(cardPanel, "name_1353795309214809000");
	}

	public void showNext() {
		CardLayout cl = (CardLayout) cardPanel.getLayout();
		log.debug("show the next screen");
		cl.next(cardPanel);
	}

	public void showChooseCase() {
		CardLayout cl = (CardLayout) cardPanel.getLayout();
		cl.show(cardPanel, "name_1353795309185814000");
	}

	public void addEvidenceFileToAddEvidenceJPanel(File file,
			MyFileFilter addEvidenceFileFilter) {
		if (addEvidenceFileFilter.accept(file)) {
			if (file.isDirectory()) {
				log.debug("File " + file.getAbsolutePath() + " is a directory");
				File[] files = file.listFiles(addEvidenceFileFilter);
				for (File file2 : files) {
					log.debug("Current file to process is "
							+ file2.getAbsolutePath());
					if (file2.isDirectory()) {
						addEvidenceFileToAddEvidenceJPanel(file2,
								addEvidenceFileFilter);
					} else {
						addEvidenceDefaultListModel.addElement(file2
								.getAbsolutePath());
					}
				}
			} else {
				addEvidenceDefaultListModel.addElement(file.getAbsolutePath());
			}
		}
	}
}
